#pragma once

#include <vector>
#include <stdexcept>
#include <cstddef>

namespace utils {

/**
 * @brief 高性能环形缓冲区实现
 * 
 * 这个类提供了一个固定大小的环形缓冲区，适用于需要频繁添加和移除元素的场景，
 * 特别是在高频交易系统中存储价格历史数据。相比std::vector和std::deque，
 * 它提供了更高效的内存使用和更好的缓存局部性。
 * 
 * @tparam T 缓冲区元素类型
 */
template <typename T>
class RingBuffer {
public:
    /**
     * @brief 构造一个指定容量的环形缓冲区
     * @param capacity 缓冲区容量
     */
    explicit RingBuffer(size_t capacity = 0)
        : capacity_(capacity)
        , size_(0)
        , head_(0)
        , tail_(0) {
        if (capacity_ > 0) {
            buffer_.resize(capacity_);
        }
    }

    /**
     * @brief 向缓冲区尾部添加元素
     * 
     * 如果缓冲区已满，最旧的元素将被覆盖
     * 
     * @param value 要添加的元素
     */
    void push_back(const T& value) {
        if (capacity_ == 0) {
            return;
        }

        buffer_[tail_] = value;
        tail_ = (tail_ + 1) % capacity_;

        if (size_ < capacity_) {
            ++size_;
        } else {
            // 缓冲区已满，覆盖最旧的元素
            head_ = (head_ + 1) % capacity_;
        }
    }

    /**
     * @brief 获取缓冲区头部元素（最旧的元素）
     * @return 头部元素的引用
     * @throws std::out_of_range 如果缓冲区为空
     */
    const T& front() const {
        if (empty()) {
            throw std::out_of_range("RingBuffer is empty");
        }
        return buffer_[head_];
    }

    /**
     * @brief 获取缓冲区尾部元素（最新的元素）
     * @return 尾部元素的引用
     * @throws std::out_of_range 如果缓冲区为空
     */
    const T& back() const {
        if (empty()) {
            throw std::out_of_range("RingBuffer is empty");
        }
        return buffer_[(tail_ + capacity_ - 1) % capacity_];
    }

    /**
     * @brief 通过索引访问元素
     * @param index 元素索引，0表示最旧的元素
     * @return 元素的引用
     * @throws std::out_of_range 如果索引超出范围
     */
    const T& operator[](size_t index) const {
        if (index >= size_) {
            throw std::out_of_range("Index out of range");
        }
        return buffer_[(head_ + index) % capacity_];
    }

    /**
     * @brief 通过索引访问元素（可修改版本）
     * @param index 元素索引，0表示最旧的元素
     * @return 元素的引用
     * @throws std::out_of_range 如果索引超出范围
     */
    T& operator[](size_t index) {
        if (index >= size_) {
            throw std::out_of_range("Index out of range");
        }
        return buffer_[(head_ + index) % capacity_];
    }

    /**
     * @brief 清空缓冲区
     */
    void clear() {
        size_ = 0;
        head_ = 0;
        tail_ = 0;
    }

    /**
     * @brief 检查缓冲区是否为空
     * @return 如果缓冲区为空则返回true
     */
    bool empty() const {
        return size_ == 0;
    }

    /**
     * @brief 检查缓冲区是否已满
     * @return 如果缓冲区已满则返回true
     */
    bool full() const {
        return size_ == capacity_;
    }

    /**
     * @brief 获取缓冲区当前元素数量
     * @return 元素数量
     */
    size_t size() const {
        return size_;
    }

    /**
     * @brief 获取缓冲区容量
     * @return 缓冲区容量
     */
    size_t capacity() const {
        return capacity_;
    }

    /**
     * @brief 调整缓冲区容量
     * 
     * 如果新容量小于当前大小，将保留最新的元素
     * 
     * @param new_capacity 新的缓冲区容量
     */
    void resize(size_t new_capacity) {
        if (new_capacity == capacity_) {
            return;
        }

        std::vector<T> new_buffer(new_capacity);
        
        // 复制元素到新缓冲区
        size_t new_size = std::min(size_, new_capacity);
        for (size_t i = 0; i < new_size; ++i) {
            // 从最新的元素开始复制
            size_t old_idx = (head_ + size_ - new_size + i) % capacity_;
            new_buffer[i] = buffer_[old_idx];
        }
        
        buffer_ = std::move(new_buffer);
        capacity_ = new_capacity;
        size_ = new_size;
        head_ = 0;
        tail_ = size_;
    }

private:
    std::vector<T> buffer_;  // 底层存储
    size_t capacity_;        // 缓冲区容量
    size_t size_;            // 当前元素数量
    size_t head_;            // 头部索引（最旧的元素）
    size_t tail_;            // 尾部索引（下一个要插入的位置）
};

} // namespace utils